package com.demo.filter;

import com.alibaba.fastjson2.JSONObject;
import com.demo.model.AuthConstants;
import com.demo.model.CodeEnum;
import com.demo.model.ResultMsg;
import com.demo.model.SecurityUser;
import com.demo.utils.JWTUtil;
import com.demo.utils.ResponseUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;
import java.util.Set;

@Component
public class TokenFiler extends OncePerRequestFilter {
    @Autowired
    private StringRedisTemplate redisTemplate;

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
            throws ServletException, IOException {

        // 获取 authorization 的值
        String authorizationValue = request.getHeader(AuthConstants.AUTHORIZATION);
        // 令牌是否存在
        if (!StringUtils.hasText(authorizationValue)) {
            ResponseUtil.writeJson(response, ResultMsg.fail(CodeEnum.TOKEN_EMPTY));
        }
        // 从请求头中获取 token
        String jwt_token = authorizationValue.replaceFirst(AuthConstants.BEARER, "");
        if (!StringUtils.hasText(jwt_token)) {
            ResponseUtil.writeJson(response, ResultMsg.fail(CodeEnum.TOKEN_EMPTY));
        }
        // 判断 token 是否有值
        if (!StringUtils.hasText(jwt_token)) {
            ResponseUtil.writeJson(response, ResultMsg.fail(CodeEnum.TOKEN_INVALID));
        }
        // 判断 Reid 中是否有值
        if (!redisTemplate.hasKey(AuthConstants.TOKEN_PREFIX + jwt_token)){
            ResponseUtil.writeJson(response, ResultMsg.fail(CodeEnum.TOKEN_INVALID));
        }
        // 解析 jwt 令牌
        String securityUserStr = JWTUtil.parseJWT(jwt_token);
        // 获取安全认证用户对象 SecurityUser 将其 json 格式字符串对象
        SecurityUser securityUser = JSONObject.parseObject(securityUserStr, SecurityUser.class);
        // 获取操作权限集合   [set转list]
        Set<String> permissionList =  securityUser.getPermissionLIst();
        List<SimpleGrantedAuthority> list = permissionList.stream().map(SimpleGrantedAuthority::new).toList();
        // 创建认证消息对象
        UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken =
                new UsernamePasswordAuthenticationToken(securityUser, null, list);

        // 将单曲用户认证的消息存放到security上下文中
        SecurityContextHolder.getContext().setAuthentication(usernamePasswordAuthenticationToken);
        // 下一个过滤器
        filterChain.doFilter(request,response);
    }
}
